🎖️GitЯра🎖️
Node / meshtastic / Meshtastic-Android / files / app / src / main / java / com / geeksville / mesh / ui / contact / ContactsViewModel.kt
Displaying Raw • Download
app/src/main/java/com/geeksville/mesh/ui/contact/ContactsViewModel.kt 78274c792318331b11ab64cd28e58e829875b8c2 (78274c79) Text, 8.63 KB
T8b949e/*
* Copyright (c) 2025 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787com.geeksville.mesh.ui.contact
Tff7b72import T7ee787androidx.lifecycle.ViewModel
Tff7b72import T7ee787androidx.lifecycle.viewModelScope
Tff7b72import T7ee787androidx.paging.PagingData
Tff7b72import T7ee787androidx.paging.cachedIn
Tff7b72import T7ee787androidx.paging.map
Tff7b72import T7ee787com.geeksville.mesh.model.Contact
Tff7b72import T7ee787dagger.hilt.android.lifecycle.HiltViewModel
Tff7b72import T7ee787kotlinx.coroutines.Dispatchers
Tff7b72import T7ee787kotlinx.coroutines.flow.Flow
Tff7b72import T7ee787kotlinx.coroutines.flow.combine
Tff7b72import T7ee787kotlinx.coroutines.flow.flatMapLatest
Tff7b72import T7ee787kotlinx.coroutines.flow.map
Tff7b72import T7ee787kotlinx.coroutines.launch
Tff7b72import T7ee787kotlinx.coroutines.runBlocking
Tff7b72import T7ee787org.jetbrains.compose.resources.getString
Tff7b72import T7ee787org.meshtastic.core.data.repository.NodeRepository
Tff7b72import T7ee787org.meshtastic.core.data.repository.PacketRepository
Tff7b72import T7ee787org.meshtastic.core.data.repository.RadioConfigRepository
Tff7b72import T7ee787org.meshtastic.core.database.entity.Packet
Tff7b72import T7ee787org.meshtastic.core.model.DataPacket
Tff7b72import T7ee787org.meshtastic.core.model.util.getChannel
Tff7b72import T7ee787org.meshtastic.core.model.util.getShortDate
Tff7b72import T7ee787org.meshtastic.core.service.ServiceRepository
Tff7b72import T7ee787org.meshtastic.core.strings.Res
Tff7b72import T7ee787org.meshtastic.core.strings.channel_name
Tff7b72import T7ee787org.meshtastic.core.ui.viewmodel.stateInWhileSubscribed
Tff7b72import T7ee787org.meshtastic.proto.channelSet
Tff7b72import T7ee787javax.inject.Inject
Tff7b72import T7ee787kotlin.collections.map Tff7b72as Te6edf3collectionsMap
Tf0883e@HiltViewModel
Tff7b72class T56d364ContactsViewModel
Tf0883e@Inject
Tff7b72constructorTb4b4b4(
Tff7b72private Tff7b72val Te6edf3nodeRepositoryTb4b4b4: Te6edf3NodeRepositoryTb4b4b4,
Tff7b72private Tff7b72val Te6edf3packetRepositoryTb4b4b4: Te6edf3PacketRepositoryTb4b4b4,
Te6edf3radioConfigRepositoryTb4b4b4: Te6edf3RadioConfigRepositoryTb4b4b4,
Te6edf3serviceRepositoryTb4b4b4: Te6edf3ServiceRepositoryTb4b4b4,
Tb4b4b4) Tb4b4b4: Te6edf3ViewModelTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3ourNodeInfo Tff7b72= Te6edf3nodeRepositoryTb4b4b4.Te6edf3ourNodeInfo
Tff7b72val Te6edf3connectionState Tff7b72= Te6edf3serviceRepositoryTb4b4b4.Te6edf3connectionState
Tff7b72val Te6edf3channels Tff7b72= Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3channelSetFlowTb4b4b4.Te6edf3stateInWhileSubscribedTb4b4b4(Te6edf3initialValue Tff7b72= Te6edf3channelSet Tb4b4b4{Tb4b4b4}Tb4b4b4)
T8b949e/**
* Non-paginated contact list.
*
* NOTE: This is kept for ShareScreen which needs a simple, non-paginated list of contacts. The main ContactsScreen
* uses [contactListPaged] instead for better performance with large contact lists.
*
* @see contactListPaged for the paginated version used in ContactsScreen
*/
Tff7b72val Te6edf3contactList Tff7b72=
Te6edf3combineTb4b4b4(
Te6edf3nodeRepositoryTb4b4b4.Te6edf3myNodeInfoTb4b4b4,
Te6edf3packetRepositoryTb4b4b4.Te6edf3getContactsTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3channelsTb4b4b4,
Te6edf3packetRepositoryTb4b4b4.Te6edf3getContactSettingsTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4) Tb4b4b4{ Te6edf3myNodeInfoTb4b4b4, Te6edf3contactsTb4b4b4, Te6edf3channelSetTb4b4b4, Te6edf3settings Tff7b72-Tff7b72>
Tff7b72val Te6edf3myNodeNum Tff7b72= Te6edf3myNodeInfoTff7b72?.Te6edf3myNodeNum Tff7b72?: Tff7b72returnTf0883e@combine Te6edf3emptyListTb4b4b4(Tb4b4b4)
T8b949e// Add empty channel placeholders (always show Broadcast contacts, even when empty)
Tff7b72val Te6edf3placeholder Tff7b72=
Tb4b4b4(T79c0ff0 Te6edf3until Te6edf3channelSetTb4b4b4.Te6edf3settingsCountTb4b4b4)Tb4b4b4.Te6edf3associate Tb4b4b4{ Te6edf3ch Tff7b72-Tff7b72>
Tff7b72val Te6edf3contactKey Tff7b72= Ta5d6ff"Tffd700$Te6edf3chTffd700${Te6edf3DataPacketTb4b4b4.Te6edf3ID_BROADCASTTffd700}Ta5d6ff"
Tff7b72val Te6edf3data Tff7b72= Te6edf3DataPacketTb4b4b4(Te6edf3bytes Tff7b72= Tff7b72nullTb4b4b4, Te6edf3dataType Tff7b72= T79c0ff1Tb4b4b4, Te6edf3time Tff7b72= T79c0ff0LTb4b4b4, Te6edf3channel Tff7b72= Te6edf3chTb4b4b4)
Te6edf3contactKey Te6edf3to Te6edf3PacketTb4b4b4(T79c0ff0LTb4b4b4, Te6edf3myNodeNumTb4b4b4, T79c0ff1Tb4b4b4, Te6edf3contactKeyTb4b4b4, T79c0ff0LTb4b4b4, Tff7b72trueTb4b4b4, Te6edf3dataTb4b4b4)
Tb4b4b4}
Tb4b4b4(Te6edf3contacts Tff7b72+ Tb4b4b4(Te6edf3placeholder Tff7b72- Te6edf3contactsTb4b4b4.Te6edf3keysTb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3valuesTb4b4b4.Te6edf3collectionsMap Tb4b4b4{ Te6edf3packet Tff7b72-Tff7b72>
Tff7b72val Te6edf3data Tff7b72= Te6edf3packetTb4b4b4.Te6edf3data
Tff7b72val Te6edf3contactKey Tff7b72= Te6edf3packetTb4b4b4.Te6edf3contact_key
T8b949e// Determine if this is my message (originated on this device)
Tff7b72val Te6edf3fromLocal Tff7b72= Te6edf3dataTb4b4b4.Te6edf3from Tff7b72=Tff7b72= Te6edf3DataPacketTb4b4b4.Te6edf3ID_LOCAL
Tff7b72val Te6edf3toBroadcast Tff7b72= Te6edf3dataTb4b4b4.Te6edf3to Tff7b72=Tff7b72= Te6edf3DataPacketTb4b4b4.Te6edf3ID_BROADCAST
T8b949e// grab usernames from NodeInfo
Tff7b72val Te6edf3user Tff7b72= Te6edf3getUserTb4b4b4(Tff7b72if Tb4b4b4(Te6edf3fromLocalTb4b4b4) Te6edf3dataTb4b4b4.Te6edf3to Tff7b72else Te6edf3dataTb4b4b4.Te6edf3fromTb4b4b4)
Tff7b72val Te6edf3node Tff7b72= Te6edf3getNodeTb4b4b4(Tff7b72if Tb4b4b4(Te6edf3fromLocalTb4b4b4) Te6edf3dataTb4b4b4.Te6edf3to Tff7b72else Te6edf3dataTb4b4b4.Te6edf3fromTb4b4b4)
Tff7b72val Te6edf3shortName Tff7b72= Te6edf3userTb4b4b4.Te6edf3shortName
Tff7b72val Te6edf3longName Tff7b72=
Tff7b72if Tb4b4b4(Te6edf3toBroadcastTb4b4b4) Tb4b4b4{
Te6edf3channelSetTb4b4b4.Te6edf3getChannelTb4b4b4(Te6edf3dataTb4b4b4.Te6edf3channelTb4b4b4)Tff7b72?.Te6edf3name Tff7b72?: Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3channel_nameTb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3userTb4b4b4.Te6edf3longName
Tb4b4b4}
Te6edf3ContactTb4b4b4(
Te6edf3contactKey Tff7b72= Te6edf3contactKeyTb4b4b4,
Te6edf3shortName Tff7b72= Tff7b72if Tb4b4b4(Te6edf3toBroadcastTb4b4b4) Ta5d6ff"Tffd700${Te6edf3dataTb4b4b4.Te6edf3channelTffd700}Ta5d6ff" Tff7b72else Te6edf3shortNameTb4b4b4,
Te6edf3longName Tff7b72= Te6edf3longNameTb4b4b4,
Te6edf3lastMessageTime Tff7b72= Te6edf3getShortDateTb4b4b4(Te6edf3dataTb4b4b4.Te6edf3timeTb4b4b4)Tb4b4b4,
Te6edf3lastMessageText Tff7b72= Tff7b72if Tb4b4b4(Te6edf3fromLocalTb4b4b4) Te6edf3dataTb4b4b4.Te6edf3text Tff7b72else Ta5d6ff"Tffd700$Te6edf3shortNameTa5d6ff: Tffd700${Te6edf3dataTb4b4b4.Te6edf3textTffd700}Ta5d6ff"Tb4b4b4,
Te6edf3unreadCount Tff7b72= Te6edf3packetRepositoryTb4b4b4.Te6edf3getUnreadCountTb4b4b4(Te6edf3contactKeyTb4b4b4)Tb4b4b4,
Te6edf3messageCount Tff7b72= Te6edf3packetRepositoryTb4b4b4.Te6edf3getMessageCountTb4b4b4(Te6edf3contactKeyTb4b4b4)Tb4b4b4,
Te6edf3isMuted Tff7b72= Te6edf3settingsTff7b72[Te6edf3contactKeyTff7b72]Tff7b72?.Te6edf3isMuted Tff7b72=Tff7b72= Tff7b72trueTb4b4b4,
Te6edf3isUnmessageable Tff7b72= Te6edf3userTb4b4b4.Te6edf3isUnmessagableTb4b4b4,
Te6edf3nodeColors Tff7b72=
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3toBroadcastTb4b4b4) Tb4b4b4{
Te6edf3nodeTb4b4b4.Te6edf3colors
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72null
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4.Te6edf3stateInWhileSubscribedTb4b4b4(Te6edf3initialValue Tff7b72= Te6edf3emptyListTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3contactListPagedTb4b4b4: Te6edf3FlowTff7b72<Te6edf3PagingDataTff7b72<Te6edf3ContactTff7b72>Tff7b72> Tff7b72=
Te6edf3combineTb4b4b4(Te6edf3nodeRepositoryTb4b4b4.Te6edf3myNodeInfoTb4b4b4, Te6edf3channelsTb4b4b4, Te6edf3packetRepositoryTb4b4b4.Te6edf3getContactSettingsTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3myNodeInfoTb4b4b4,
Te6edf3channelSetTb4b4b4,
Te6edf3settingsTb4b4b4,
Tff7b72-Tff7b72>
Te6edf3TripleTb4b4b4(Te6edf3myNodeInfoTff7b72?.Te6edf3myNodeNumTb4b4b4, Te6edf3channelSetTb4b4b4, Te6edf3settingsTb4b4b4)
Tb4b4b4}
Tb4b4b4.Te6edf3flatMapLatest Tb4b4b4{ Tb4b4b4(Te6edf3myNodeNumTb4b4b4, Te6edf3channelSetTb4b4b4, Te6edf3settingsTb4b4b4) Tff7b72-Tff7b72>
Te6edf3packetRepositoryTb4b4b4.Te6edf3getContactsPagedTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3map Tb4b4b4{ Te6edf3pagingData Tff7b72-Tff7b72>
Te6edf3pagingDataTb4b4b4.Te6edf3map Tb4b4b4{ Te6edf3packet Tff7b72-Tff7b72>
Tff7b72val Te6edf3data Tff7b72= Te6edf3packetTb4b4b4.Te6edf3data
Tff7b72val Te6edf3contactKey Tff7b72= Te6edf3packetTb4b4b4.Te6edf3contact_key
T8b949e// Determine if this is my message (originated on this device)
Tff7b72val Te6edf3fromLocal Tff7b72= Te6edf3dataTb4b4b4.Te6edf3from Tff7b72=Tff7b72= Te6edf3DataPacketTb4b4b4.Te6edf3ID_LOCAL
Tff7b72val Te6edf3toBroadcast Tff7b72= Te6edf3dataTb4b4b4.Te6edf3to Tff7b72=Tff7b72= Te6edf3DataPacketTb4b4b4.Te6edf3ID_BROADCAST
T8b949e// grab usernames from NodeInfo
Tff7b72val Te6edf3user Tff7b72= Te6edf3getUserTb4b4b4(Tff7b72if Tb4b4b4(Te6edf3fromLocalTb4b4b4) Te6edf3dataTb4b4b4.Te6edf3to Tff7b72else Te6edf3dataTb4b4b4.Te6edf3fromTb4b4b4)
Tff7b72val Te6edf3node Tff7b72= Te6edf3getNodeTb4b4b4(Tff7b72if Tb4b4b4(Te6edf3fromLocalTb4b4b4) Te6edf3dataTb4b4b4.Te6edf3to Tff7b72else Te6edf3dataTb4b4b4.Te6edf3fromTb4b4b4)
Tff7b72val Te6edf3shortName Tff7b72= Te6edf3userTb4b4b4.Te6edf3shortName
Tff7b72val Te6edf3longName Tff7b72=
Tff7b72if Tb4b4b4(Te6edf3toBroadcastTb4b4b4) Tb4b4b4{
Te6edf3channelSetTb4b4b4.Te6edf3getChannelTb4b4b4(Te6edf3dataTb4b4b4.Te6edf3channelTb4b4b4)Tff7b72?.Te6edf3name Tff7b72?: Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3channel_nameTb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3userTb4b4b4.Te6edf3longName
Tb4b4b4}
Te6edf3ContactTb4b4b4(
Te6edf3contactKey Tff7b72= Te6edf3contactKeyTb4b4b4,
Te6edf3shortName Tff7b72= Tff7b72if Tb4b4b4(Te6edf3toBroadcastTb4b4b4) Ta5d6ff"Tffd700${Te6edf3dataTb4b4b4.Te6edf3channelTffd700}Ta5d6ff" Tff7b72else Te6edf3shortNameTb4b4b4,
Te6edf3longName Tff7b72= Te6edf3longNameTb4b4b4,
Te6edf3lastMessageTime Tff7b72= Te6edf3getShortDateTb4b4b4(Te6edf3dataTb4b4b4.Te6edf3timeTb4b4b4)Tb4b4b4,
Te6edf3lastMessageText Tff7b72= Tff7b72if Tb4b4b4(Te6edf3fromLocalTb4b4b4) Te6edf3dataTb4b4b4.Te6edf3text Tff7b72else Ta5d6ff"Tffd700$Te6edf3shortNameTa5d6ff: Tffd700${Te6edf3dataTb4b4b4.Te6edf3textTffd700}Ta5d6ff"Tb4b4b4,
Te6edf3unreadCount Tff7b72= Te6edf3runBlockingTb4b4b4(Te6edf3DispatchersTb4b4b4.Te6edf3IOTb4b4b4) Tb4b4b4{ Te6edf3packetRepositoryTb4b4b4.Te6edf3getUnreadCountTb4b4b4(Te6edf3contactKeyTb4b4b4) Tb4b4b4}Tb4b4b4,
Te6edf3messageCount Tff7b72= Te6edf3runBlockingTb4b4b4(Te6edf3DispatchersTb4b4b4.Te6edf3IOTb4b4b4) Tb4b4b4{ Te6edf3packetRepositoryTb4b4b4.Te6edf3getMessageCountTb4b4b4(Te6edf3contactKeyTb4b4b4) Tb4b4b4}Tb4b4b4,
Te6edf3isMuted Tff7b72= Te6edf3settingsTff7b72[Te6edf3contactKeyTff7b72]Tff7b72?.Te6edf3isMuted Tff7b72=Tff7b72= Tff7b72trueTb4b4b4,
Te6edf3isUnmessageable Tff7b72= Te6edf3userTb4b4b4.Te6edf3isUnmessagableTb4b4b4,
Te6edf3nodeColors Tff7b72=
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3toBroadcastTb4b4b4) Tb4b4b4{
Te6edf3nodeTb4b4b4.Te6edf3colors
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72null
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4.Te6edf3cachedInTb4b4b4(Te6edf3viewModelScopeTb4b4b4)
Tff7b72fun Td2a8ffgetNodeTb4b4b4(Te6edf3userIdTb4b4b4: Tffa657String?Tb4b4b4) Tff7b72= Te6edf3nodeRepositoryTb4b4b4.Te6edf3getNodeTb4b4b4(Te6edf3userId Tff7b72?: Te6edf3DataPacketTb4b4b4.Te6edf3ID_BROADCASTTb4b4b4)
Tff7b72fun Td2a8ffdeleteContactsTb4b4b4(Te6edf3contactsTb4b4b4: Te6edf3ListTff7b72<Tffa657StringTff7b72>Tb4b4b4) Tff7b72=
Te6edf3viewModelScopeTb4b4b4.Te6edf3launchTb4b4b4(Te6edf3DispatchersTb4b4b4.Te6edf3IOTb4b4b4) Tb4b4b4{ Te6edf3packetRepositoryTb4b4b4.Te6edf3deleteContactsTb4b4b4(Te6edf3contactsTb4b4b4) Tb4b4b4}
Tff7b72fun Td2a8ffsetMuteUntilTb4b4b4(Te6edf3contactsTb4b4b4: Te6edf3ListTff7b72<Tffa657StringTff7b72>Tb4b4b4, Te6edf3untilTb4b4b4: Tffa657LongTb4b4b4) Tff7b72=
Te6edf3viewModelScopeTb4b4b4.Te6edf3launchTb4b4b4(Te6edf3DispatchersTb4b4b4.Te6edf3IOTb4b4b4) Tb4b4b4{ Te6edf3packetRepositoryTb4b4b4.Te6edf3setMuteUntilTb4b4b4(Te6edf3contactsTb4b4b4, Te6edf3untilTb4b4b4) Tb4b4b4}
Tff7b72fun Td2a8ffgetContactSettingsTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3packetRepositoryTb4b4b4.Te6edf3getContactSettingsTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72fun Td2a8ffgetUserTb4b4b4(Te6edf3userIdTb4b4b4: Tffa657String?Tb4b4b4) Tff7b72= Te6edf3nodeRepositoryTb4b4b4.Te6edf3getUserTb4b4b4(Te6edf3userId Tff7b72?: Te6edf3DataPacketTb4b4b4.Te6edf3ID_BROADCASTTb4b4b4)
Tb4b4b4}
Served by rngit 1.5.0 - Generated in 0.08s